package Phase2;

//import java.util.ArrayList;
import java.io.Serializable;
import java.util.*;

/**
 * 
 * Class that holds a list of Nodes and tracks the largest and smallest ones
 * 
 * @author jazzinsa
 *
 */
public class NodeList implements Iterable<Node>, Serializable
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private TreeSet<Node> nodeSet;
	
	/**
	 * default constructor 
	 * @pre none
	 * @post list initialized to new list
	 */
	public NodeList()
	{
		init();
	}
	
	private void init()
	{
		nodeSet = new TreeSet<Node>();
	}
	
	/**
	 * add a node to the list
	 * @param node - node to be added
	 * @return whether node was added or not
	 * @pre node != null
	 * @post return true if node was added, false if already in list
	 */
	public boolean add(Node node)
	{
		return nodeSet.add(node);
	}
	
	/**
	 * adds all nodes to set
	 * @param nodes - list of nodes to be added
	 * @return whether nodes were added to list or not
	 * @pre nodes != null
	 * @post return true if nodes were added, false if already in list
	 */
	public boolean addAll(NodeList nodes)
	{
		return nodeSet.addAll(nodes.nodeSet);
	}

	/**
	 * removes a node from the list
	 * @param node - node to be removed
	 * @return whether node was removed or not
	 * @pre node != null
	 * @post return true if node was removed, false if not
	 */
	public boolean remove(Node node)
	{
		return nodeSet.remove(node);
	}
	
	/**
	 * Replaces a Node in the set with another Node
	 * @param replacer Node to add to the list
	 * @param replaced Node to remove from the list
	 * @return True if replacer is added to list
	 * @pre none
	 * @post this.contains(replaced) == false && this.contains(replacer) == true;
	 */
	public boolean replace(Node replaced, Node replacer)
	{
		this.nodeSet.remove(replaced);
		return this.nodeSet.add(replacer);
	}
	
	/**
	 * returns the size of the list
	 * @return size of list
	 * @pre none
	 * @post return size of the list of nodes
	 */
	public int size()
	{
		return nodeSet.size();
	}
	
	/**
	 * return whether the node is a member of the list
	 * @param node - node to be found in the list
	 * @return whether the node was in the list
	 * @pre node != null
	 * @post return true if node found in list, false in not
	 */
	public boolean contains(Node node)
	{
		return nodeSet.contains(node);
	}
	
	/**
	 * Returns the node with the highest id
	 * @return node with highest id
	 * @pre None
	 * @post return largest node in list, if empty return null
	 */
	public Node getMax()
	{
		//return this.maxNode;
		try
		{
			return nodeSet.last();
		}
		catch (NoSuchElementException e)
		{
			return null;
		}
	}
	
	/**
	 * Returns the node with the lowest id
	 * @return node with lowest id
	 * @pre none
	 * @post return smallest node in list, if empty return null
	 */
	public Node getMin()
	{
		//return this.minNode;
		try
		{
			return nodeSet.first();
		}
		catch (NoSuchElementException e)
		{
			return null;
		}
	}
	
	/**
	 * clears the node list
	 * @pre none
	 * @post list is now size 0, all elements are removed
	 */
	public void clear()
	{
		init();
		nodeSet.clear();
	}
	
	/**
	 * returns an array of the node list id's as an integer array
	 * @return list of id's as integer array
	 * @pre none
	 * @post return list of id's as integer array
	 */
	public int[] idToArray() throws InterruptedException
	{
		int[] id = new int[nodeSet.size()];
		int count = 0;
		for(Node node : nodeSet)
		{
			id[count] = node.getId(false);
			count++;
		}
		return id;
	}
	/**
	 * Creates a string representation of the list
	 * @return string representation of the list
	 * @pre none
	 * @post return string representing the list 
	 */
	public String toString()
	{
		String result = new String();
		if(nodeSet.size() == 0)
		{
			result += "";
		}
		else
		{
			result += ""; 
			Iterator<Node> it = nodeSet.iterator();
			try
			{
				while (it.hasNext())
				{
					result += " " + ((Node) it.next()).getId(false);
				}
			}
			catch (InterruptedException e)
			{
				result = "Node State invalid. InterrupedException thrown while waiting for Node to get into a valid state.";
			}
		}
		return result;
	}
	/*
	 * Returns a string representation of the list
	 * @return string representation
	 * @pre None
	 * @post return string representing the list
	 */
/*	public String print()
	{
		String result = new String();
		if(nodeSet.size() == 0)
		{
			result += "\nNodes: <empty>";
		}
		else
		{
			result += "\nNodes:"; 
			Iterator<Node> it = nodeSet.iterator();
		
			while (it.hasNext())
			{
				result += it.next().toString();
			} 
		}
		return result;
	}*/

	@Override
	public Iterator<Node> iterator() 
	{
		return nodeSet.iterator();
	}
}
